package util

import (
	"reflect"
	"strings"
	"sync"
)

// BuildTree 构建树形结构
func BuildTree[T any](list []*T, rootId string, setChildren func(parent *T, children []*T)) []*T {
	// 等待所有 goroutine 执行结束
	wg := &sync.WaitGroup{}
	// 存储最终的结果集
	retList := make([]*T, 0, 0)
	for _, t := range list {
		// 找到根节点，进行递归构建
		if GetParentId(t) == rootId {
			// 递归构建出当前根节点下的所有子节点
			wg.Add(1)
			go recursionFn(list, t, setChildren, wg)
			// 将根节点添加至结果集合中
			retList = append(retList, t)
		}
	}
	// 等待所有递归都结束再返回结果
	wg.Wait()
	return retList
}

func recursionFn[T any](list []*T, t *T, setChildren func(parent *T, children []*T), wg *sync.WaitGroup) {
	defer wg.Done()
	// 递归收集当前节点的子节点集合
	children := getChildList(list, t)
	if children != nil && len(children) > 0 {
		setChildren(t, children)
	}
	// 递归构建当前节点的子节点的子节点集合，直到遍历到叶子节点
	for _, child := range children {
		wg.Add(1)
		go recursionFn(list, child, setChildren, wg)
	}
}

func getChildList[T any](list []*T, t *T) []*T {
	tList := make([]*T, 0, 0)
	id := GetId(t)
	for _, n := range list {
		if GetParentId(n) == id {
			tList = append(tList, n)
		}
	}
	// 如果是叶子节点 返回空数组
	return tList
}

func GetId[T any](t *T) string {
	return reflect.ValueOf(*t).FieldByName("Id").String()
}

func GetParentId[T any](t *T) string {
	return reflect.ValueOf(*t).FieldByName("ParentId").String()
}

// CalcTreeLevel 计算树的层级
func CalcTreeLevel(treePath string) int {
	if treePath == "" {
		return 1
	}
	return len(strings.Split(treePath, ",")) + 1
}
